﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Windows.Forms;
using System.Reflection;

namespace ui
{
    public partial class frmMain : Form
    {
        #region Declarations

        public _settings settings = new _settings();
        List<_control> controls = new List<_control>();
        _control selected = null;

        public Font mainFont = new Font("Consolas",8);

        #endregion

        #region UI

        public frmMain()
        {
            InitializeComponent();
        }

        private void window_MouseDown(object sender, MouseEventArgs e)
        {
            selectObject(null);
        }

        public void pic_MouseDown(object sender, MouseEventArgs e)
        {
            selected = getSender(sender);
            selectObject(selected);
        }

        private void tsAdd_Click(object sender, EventArgs e)
        {
            add();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            Type[] types = Assembly.GetExecutingAssembly().GetTypes();
            foreach (Type type in types)
            {
                if (type.IsSubclassOf(typeof(_control)))
                {
                    lsClasses.Items.Add(type.ToString());
                }
            }

            createnew();
        }

        private void window_Paint(object sender, PaintEventArgs e)
        {
            Brush fill = new HatchBrush(HatchStyle.SmallGrid, Color.WhiteSmoke, Color.LightGray);
            e.Graphics.FillRectangle(fill,new Rectangle(0,0,(int)width.Value,(int)height.Value));
        }

        private void tsFront_Click(object sender, EventArgs e)
        {
            tofront();
        }

        private void tsBack_Click(object sender, EventArgs e)
        {
            toback();
        }

        private void split1_Panel1_Click(object sender, EventArgs e)
        {
            selectObject(null);
        }

        private void tsRemove_Click(object sender, EventArgs e)
        {
            remove();
        }

        private void tab_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tab.SelectedIndex == 1)
            {
                code.Clear();
                code.Text = _functions.generateCode(controls,(int)gridW.Value,(int)gridH.Value);
            }
            else if (tab.SelectedIndex == 2)
            {
                xml.Clear();
                xml.Text = _functions.generateXML(controls,settings);
            }
        }

        private void tsCompile_Click(object sender, EventArgs e)
        {
            compile();
        }

        private void tsGDI_Click(object sender, EventArgs e)
        {
            rendergdi();
        }

        private void tsDisplay_Click(object sender, EventArgs e)
        {
            render4d();
        }

        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            remove();
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            remove();
        }

        private void sendToFrontToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tofront();
        }

        private void sendToBackToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            toback();
        }

        private void bringToFrontToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tofront();
        }

        private void sendToBackToolStripMenuItem_Click(object sender, EventArgs e)
        {
            toback();
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            add();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            save.Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.*";
            save.ShowDialog();

            if (save.FileName == "") return;

            _functions.saveFile(save.FileName, controls,settings);
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            createnew();
        }
        
        private void cmdApply_Click(object sender, EventArgs e)
        {
            apply();
            xml.Text = _functions.generateXML(controls, settings);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            open.Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.*";
            open.ShowDialog();

            if (open.FileName == "") return;

            _functions.loadFile(open.FileName, controls, out settings, this, window);
        }

        #endregion

        #region UI/Editor Functions

        _control getSender(object sender)
        {
            foreach (_control c in controls)
            {
                if (c.pic == (Panel)sender)
                {
                    return c;
                }
            }

            return null;
        }

        int countControls(ControlTypes type)
        {
            int count = 0;
            foreach (_control c in controls)
            {
                if (c.type == type) count++;
            }

            return count;
        }

        void selectObject(_control c)
        {
            foreach (_control con in controls)
            {
                con.selected = false;
            }

            if (c == null)
            {
                props.SelectedObject = null;
            }
            else
            {
                switch (c.type)
                {
                    case ControlTypes.Button:
                        props.SelectedObject = (_button)c;
                        c.selected = true;
                        break;
                    case ControlTypes.Frame:
                        props.SelectedObject = (_frame)c;
                        c.selected = true;
                        break;
                    case ControlTypes.Window:
                        props.SelectedObject = (_window)c;
                        c.selected = true;
                        break;
                }
            }

            window.Invalidate();
        }

        void apply()
        {
            settings.width = (int)width.Value;
            settings.height = (int)height.Value;
            settings.charwidth = (int)gridW.Value;
            settings.charheight = (int)gridH.Value;

            refresh();
        }

        public void refresh()
        {
            window.Width = settings.width;
            window.Height = settings.height;
            window.Invalidate();

            width.Value = settings.width;
            height.Value = settings.height;
            gridW.Value = settings.charwidth;
            gridH.Value = settings.charheight;
        }

        void createnew()
        {
            settings.width = 240;
            settings.height = 320;
            settings.charwidth = 7;
            settings.charheight = 8;

            foreach (_control c in controls)
            {
                c.pic.Dispose();
            }

            controls.Clear();

            selected = null;
            selectObject(null);

            refresh();
        }

        void remove()
        {
            if (selected != null)
            {
                selected.pic.Dispose();
                controls.Remove(selected);
                selected = null;
                selectObject(null);
            }
        }

        void tofront()
        {
            if (selected != null)
            {
                selected.pic.BringToFront();
            }
        }

        void toback()
        {
            if (selected != null)
            {
                selected.pic.SendToBack();
            }
        }

        void add()
        {
            if (lsClasses.SelectedItem != null)
            {
                _control _c = (_control)Activator.CreateInstance(Type.GetType(lsClasses.SelectedItem.ToString()));

                _c.parent = this; 

                _c.width = settings.charwidth * 5;
                _c.height = settings.charheight * 5;

                _c.setup(window);
                _c.name = _c.type.ToString() + countControls(_c.type);
                _c.pic.MouseDown += new MouseEventHandler(pic_MouseDown);
                
                controls.Add(_c);
            }
        }

        codebase.UI.Renderer_GDI gdi = new codebase.UI.Renderer_GDI();
        codebase.UI.Renderer_4DSPE dddd = new codebase.UI.Renderer_4DSPE();
        codebase.UI.WindowManager man;

        object obj;

        void compile()
        {
            if (code.Text == "") return;

            lstErrors.Items.Clear();

            man = new codebase.UI.WindowManager(gdi);

            cs2Dreflection reflection = new cs2Dreflection();

            System.CodeDom.Compiler.CompilerResults result = reflection.compileScript(code.Text);

            foreach (System.CodeDom.Compiler.CompilerError err in result.Errors)
            {
                lstErrors.Items.Add("[Number: " + err.ErrorNumber + " Fehler: \"" + err.ErrorText + "\" Line: " + err.Line + "]");
            }

            if (result.Errors.HasErrors == true) return; else lstErrors.Items.Add("Compiling of UI Code successfull!");

            Assembly asm = result.CompiledAssembly;
            Type cls = asm.GetType("codebase.Window0");
            obj = Activator.CreateInstance(cls, man);
        }

        void render4d()
        {
            if (obj != null)
            {
                lstErrors.Items.Add("Connecting to Display");

                dddd.SPE.Initialize("COM7", 9600);
                dddd.SPE.TouchEnable();
                dddd.SPE.SetFont((int)SPE.FONT1);

                lstErrors.Items.Add("Drawing UI");

                man.screen = dddd;
                man.Redraw();

                lstErrors.Items.Add("Done");
            }
        }

        void rendergdi()
        {
            if (obj != null)
            {
                lstErrors.Items.Add("Drawing UI");

                man.screen = gdi;

                gdi.Width = settings.width;
                gdi.Height = settings.height;

                man.Redraw();

                lstErrors.Items.Add("Flipping Backbuffer");

                picPreview.Image = gdi.backbuffer;

                lstErrors.Items.Add("Done");
            }
        }

        #endregion
    }
}
